#ifndef _common_h_
#define _common_h_

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>

#include <android/log.h>
#include <string>

#include "base.h"

//using namespace std;

_BEGIN

#define LOG_NAME "media"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_NAME ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_NAME ,__VA_ARGS__)

#define udi_erro_log LOGE
#define udi_info_log LOGD

#define UDP_BUF_SIZE 1400

#define _AUDIO_SAMPLE_RATE 16000


#define IPC_VIDEO_DELAY_T 1200

#define SINGLE_STREAM_SINGLE_PICTURE_MODE (1 - 1)
#define PICTURE_IN_PICTURE_MODE (6 - 1)
#define FOUR_PICTURE_MODE (3 - 1)

#define MIN_THREAD_STACK_SIZE		(16 * 1024)
#define MIDDLE_THREAD_STACK_SIZE	(1024 * 1024)
#define NORMAL_THREAD_STACK_SIZE	(16 * 1024 * 1024)
#define DEFAULT_THREAD_STACK_SIZE	(1 * 1024 * 1024)

#define MAIN_VIDEO_STREAM_BIT_RATE (6 * 1024 * 1024)
#define NORMAL_VIDEO_STREAM_BIT_RATE (2 * 1024 * 1024)
#define PREVIEW_VIDEO_STREAM_BIT_RATE (380 * 1024)
#define MIDDLE_VIDEO_STREAM_BIT_RATE (1 * 1024 * 1024)

#define UDP_PACKAGE_KB_SIZE 1
#define EACH_SIZE 1400

#define MAX_FRAME_NUM_SIZE		(EACH_SIZE * UDP_PACKAGE_KB_SIZE)
#define VIDEO_FRAME_CACHE_SIZE MAIN_VIDEO_STREAM_BIT_RATE
#define AUDIO_FRAME_CACHE_SIZE (MAX_FRAME_NUM_SIZE*10)
#define VIDEO_I_FRAME_CACHE_SIZE (1024 * 1024)

#define MAIN_VIDEO_BLOCK_SIZE MAIN_VIDEO_STREAM_BIT_RATE
#define NORMAL_VIDEO_BLOCK_SIZE NORMAL_VIDEO_STREAM_BIT_RATE
#define PREVIEW_VIDEO_BLOCK_SIZE PREVIEW_VIDEO_STREAM_BIT_RATE

static const unsigned int udpVideoBlockBufMaxNumber = 500;
static const unsigned int udpVideoPreviewBlockSize = PREVIEW_VIDEO_BLOCK_SIZE;
static const unsigned int udpVideoBlockSize = NORMAL_VIDEO_BLOCK_SIZE;
static const unsigned int udpVideoMainBlockSize = MAIN_VIDEO_BLOCK_SIZE;
static const unsigned int udpVideoServerBlockSize = NORMAL_VIDEO_STREAM_BIT_RATE * 2;
static const unsigned int udpVideoServerMainBlockSize = MIDDLE_VIDEO_STREAM_BIT_RATE * 2;
static const unsigned int udpAudioBlockBufMaxNumber = 500;
static const unsigned int udpAudioBlockSize = 800 * 1024;
static const unsigned int tcpVideoAudioBufMaxNumber = 1024;
static const unsigned int tcpVideoAudioBlockSize = NORMAL_VIDEO_STREAM_BIT_RATE * 2;
static const unsigned int tcpVideoAudioMainBlockSize = MAIN_VIDEO_STREAM_BIT_RATE * 2;

static const unsigned int udpVideoClientSendBlockBufMaxNumber = 500;
static const unsigned int udpVideoClientSendBlockSize = NORMAL_VIDEO_STREAM_BIT_RATE;
static const unsigned int udpVideoClientSendBigBlockSize = MIDDLE_VIDEO_STREAM_BIT_RATE;
static const unsigned int udpAudioClientSendBlockBufMaxNumber = 500;
static const unsigned int udpAudioClientSendBlockSize = 700 * 1024;

#define UDP_SYS_SOCK_BUF_COMMON_SIZE 8 * 1024 * 1024
static const unsigned int udpServerSysSockSendBufSize = UDP_SYS_SOCK_BUF_COMMON_SIZE;
static const unsigned int udpServerSysSockRecvBufSize = UDP_SYS_SOCK_BUF_COMMON_SIZE;
static const unsigned int udpClientSysSockSendBufSize = UDP_SYS_SOCK_BUF_COMMON_SIZE;
static const unsigned int udpClientSysSockRecvBufSize = UDP_SYS_SOCK_BUF_COMMON_SIZE;

#define IDR_FRATURE 0x05
#define SEI_FEATURE 0x06
#define SPS_FEATURE 0x07
#define PPS_FEATURE 0x08
#define checkKeyFrame(p) (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x01 && (p[4] & 0x1F) == SPS_FEATURE)

//type == 1, video data; type == 2, audio data
#define VIDEO_DATA 1
#define AUDIO_DATA 2
typedef void(*MediaRecvCallBackFunc)(const int type, const char* mac_addr, const int media_id, const unsigned char *data, const int data_size, const unsigned int time_stamp);


int create_thread_small(pthread_t *pid, void*(*thread_callback)(void*), void *arg);
int create_thread_middle(pthread_t *pid, void*(*thread_callback)(void*), void *arg);
int create_thread_normal(pthread_t *pid, void*(*thread_callback)(void*), void *arg);

#define CLOSE_FILE(fp) \
do \
{ \
	if (fp) \
	{ \
		fclose(fp); \
		fp = NULL; \
	} \
} while (0);

FILE* openFileRB(const char *name);
FILE* openFileWR(const char *name);

#define CLOSE_THREAD(pid) \
do \
{ \
	if (pid > 0) \
	{ \
		pthread_join(pid, NULL); \
	} \
	pid = 0; \
} while (0);

int getAudioSampleRate(const unsigned char *audioData);

typedef enum _udpUserType
{
	eUdpServer = 1,
	eUdpClient = 2,
}UdpUserType;

typedef struct recvData
{
	int count;
	unsigned char buf[UDP_BUF_SIZE];
	struct sockaddr_in addr;
	struct recvData *pNext;
}RecvData;

typedef struct _BufferInfo
{
	unsigned char *pData;
	int nSize;
	int nFlag;
	struct _BufferInfo *pNext;
}BufferInfo, *lpBufferInfo;

typedef struct _BlockInfo
{
	sem_t m_Semaphore;
	pthread_mutex_t m_Lock;
	BufferInfo *m_Push;
	BufferInfo *m_Pop;
	BufferInfo *m_pInfo;
	unsigned char *m_pData;
	unsigned char *m_pCurr;
	int m_nInfoSize;
	int m_nDataSize;
}BlockInfo, *lpBlockInfo;

struct internalCaptureData
{
	int sock;
	pthread_mutex_t Lock;
	sem_t taskSem;
	char process[256];
	struct recvData *emptyData;
	struct recvData *recvData;
	void(*pCallBack)(struct recvData *);
};

struct internalTask
{
	pthread_mutex_t Lock;
	sem_t taskSem;
	struct recvData *recvData;
	RecvData *recvDataLast;
	void(*pCallBack)(struct recvData *);
};

struct recvData *CreateChain(int length);
void InsertHead(struct recvData **dst, struct recvData *src);
void InsertTail(struct recvData **dst, struct recvData *src);
void InsertTailEx(RecvData **dst, RecvData *src, RecvData **dstLast);
struct recvData *GetHeadChain(struct recvData **dst);
void releaseChain(struct recvData **ppHead);

int udpServerBind(unsigned short port);
int udpClientBind(unsigned short port);
int udpClientBindEx(const unsigned short port, const unsigned int sendBufSize, const unsigned int recvBufSize);

int initVideoPreviewBlock(BlockInfo *pBlockInfo);
int initVideoBlock(BlockInfo *pBlockInfo);
int initVideoMainBlock(BlockInfo *pBlockInfo);
int initAudioBlock(BlockInfo *pBlockInfo);
int initVideoServerBlock(BlockInfo *pBlockInfo);
int initVideoServerMainBlock(BlockInfo *pBlockInfo);
int initVideoAudioBlock(BlockInfo *pBlockInfo);
int initVideoAudioMainBlock(BlockInfo *pBlockInfo);
int initClientSendVideoBlock(BlockInfo *pBlockInfo);
int initClientSendBigVideoBlock(BlockInfo *pBlockInfo);
int initClientSendAudioBlock(BlockInfo *pBlockInfo);
int InitBlockInfoBuffer(BlockInfo *pBlockInfo, int nInfoSize, int nDataSize, unsigned char *pBuf, int nBufCount);
int PushBlockInfoData(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char *pFrontData, const int iFrontSize);
int pushBlock(BlockInfo *pBlockInfo, unsigned char *pData, int iSize);
int pushBlockEx(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char type);
int pushBlo(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char *pf, const int ifSize);
int PopBlockInfoData(BlockInfo *pBlockInfo, void(*pFunc)(const unsigned char*, const int, void*), void* arg);
int PopBlockInfoDataNotConst(BlockInfo *pBlockInfo, void(*pFunc)(unsigned char*, const int, void*), void* arg);
int PopBlockInfoDataEx(BlockInfo *pBlockInfo, void(*pFunc)(const unsigned char*, const int, void*), void* arg, int(*loopConditionFunc)(), int timeOut);
int PopBlockInfoDataExNotConst(BlockInfo *pBlockInfo, void(*pFunc)(unsigned char*, const int, void*), void* arg, int(*loopConditionFunc)(void *arg), int timeOut);
int PopBlockInfoDataExNotConst2(BlockInfo *pBlockInfo, void(*pFunc)(unsigned char*, const int, void*), void* arg, int *loopCondition, int timeOut);
void releaseBlock(BlockInfo *pBlockInfo);

int startInternalTask(struct internalCaptureData *pIC);

struct internalTask *createTask(void(*pCallBack)(struct recvData *));
void PushTask(struct internalTask *pIT, struct recvData *src);

int IsExit();
void setIsExit(int value);
int IsLoop();

void printf_ex(const char *name, const unsigned char *data, const int data_size);
int getIpNumFromRtspUrl(const char *url);
void externInit();
void externExit();
unsigned int GetTickCount();
int getAudioSampleRate(const unsigned char *audioData);

_END
#endif
